// parse string like:
// '1 year 2 months 3 days 4 hours 5 minutes 6 seconds 7 milliseconds'
// into object:
// { year: 1, months: 2, days: 3, hours: 4,
//   minutes: 5, seconds: 6, milliseconds: 7 }
export function parseStringToUnitValue(s) {
  const units = [
    'MILLISECOND',
    'SECOND',
    'MINUTE',
    'HOUR',
    'DAY',
    'MONTH',
    'YEAR'
  ];
  const unitsPlural = units.map(u => `${u}s`);
  const result = {};
  const unitReg = new RegExp(
    `${unitsPlural.join('|')}|${units.join('|')}`,
    'ig'
  );
  const valueReg = /-?[^0]?[0-9]+(\.[0-9]+)?/g;
  const len = s.length;

  while (unitReg.lastIndex < len && valueReg.lastIndex < len) {
    const valueMatch = valueReg.exec(s);
    const unitMatch = unitReg.exec(s);

    if (valueMatch && unitMatch) {
      const [value] = valueMatch;
      const [unit] = unitMatch;
      const floatValue = parseFloat(value);
      if (Number.isNaN(floatValue)) {
        throw new Error(
          `value is not valid at index ${valueReg.lastIndex}. string: ${s}`
        );
      }
      result[unit] = floatValue;
      valueReg.lastIndex = unitReg.lastIndex;
    } else if (!unitMatch) {
      break;
    }
  }
  return result;
}

// get milliseconds from object function parseStringToUnitValue parsed
export function getMillisecondsFromUnitValue(obj) {
  const msPerS = 1000;
  const msPerMi = 60 * msPerS;
  const msPerH = 60 * msPerMi;
  const msPerD = 24 * msPerH;
  const msPerMo = 30 * msPerD;
  const msPerY = 12 * msPerMo;

  return Object.keys(obj).reduce((sum, unit) => {
    const value = obj[unit];
    let milliseconds = 0;
    switch (unit.toUpperCase()) {
      case 'MILLISECOND':
      case 'MILLISECONDS':
        milliseconds = value;
        break;
      case 'SECOND':
      case 'SECONDS':
        milliseconds = value * msPerS;
        break;
      case 'MINUTE':
      case 'MINUTES':
        milliseconds = value * msPerMi;
        break;
      case 'HOUR':
      case 'HOURS':
        milliseconds = value * msPerH;
        break;
      case 'DAY':
      case 'DAYS':
        milliseconds = value * msPerD;
        break;
      case 'MONTH':
      case 'MONTHS':
        milliseconds = value * msPerMo;
        break;
      case 'YEAR':
      case 'YEARS':
        milliseconds = value * msPerY;
        break;
      default:
    }
    return sum + milliseconds;
  }, 0);
}

export function getMillisecondsOfReadableDateTime(string) {
  return getMillisecondsFromUnitValue(parseStringToUnitValue(string));
}

export function secondsToHMS(seconds, precise = 3) {
  const prefixZero = n => (n < 10 && n >= 0 ? `0${n}` : `${n}`);
  const steps = [24 * 60 * 60, 60 * 60, 60, 1];

  // 将秒转换为 时 分 秒
  function toHMS(
    s,
    arr = steps.slice(steps.length - precise),
    result = [],
    prefix = true
  ) {
    if (arr.length <= 0) {
      return prefix ? result.map(prefixZero) : result;
    }
    const d = arr.shift();
    result.push(Math.floor(s / d));
    return toHMS(s % d, arr, result, prefix);
  }

  return toHMS(seconds);
}

export function secondsToReduceHMS(seconds, precise) {
  const hms = secondsToHMS(seconds, precise);
  for (let i = 0; i < hms.length; i += 1) {
    const value = hms[i];
    if (value !== '00') {
      return hms.slice(i);
    }
  }
  return hms;
}

export function secondsToMS(seconds) {
  const [m, s] = secondsToReduceHMS(seconds, 2);
  return `${m}'${s}''`;
}
